package common;

import java.io.Serializable;

/**
 * 
 * @author Flavio Ferrara 
 * Rappresenta una Mappa passata al client. Viene riempita solo con le informazioni necessarie.
 * Nel caso di richiesta della vista di un dinosauro, rappresenta quella porzione di mappa
 * 
 * Il client deve conoscere:
 * - origine
 * - dimensione
 * perogni Casella:
 *  - acqua/terra/buio/vege/carogna/dino
 * se vege, carogna:
 *  - energia
 *  se dino:
 *  - id
 */
public class UserMap implements Serializable{
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int size;
	private int originX;
	private int originY;

	public enum BoxType { WATER, LAND, DARK, MEAT, VEGE, DINO }
	/**
	 * map[i][j] == {'a','t','b','c','v','d'}
	 */
	private BoxType[][] map;
	/**
	 * values[i][j] == {0, k} | k > 0
	 * map[i][j] == {WATER,LAND,DARK} <=> values[i][j] == 0
	 * map[i][j] == {MEAT, VEGE, DINO} <=> values[i][j] > 0
	 */
	private int[][] values;
	
	public UserMap(int size, int originX, int originY, BoxType[][] boxes){
		this.size = size;
		this.originX = originX;
		this.originY = originY;
		
		this.values = new int[size][size];
		this.map = new BoxType[size][size];
		for (int i = 0;i < this.size;i++){
			System.arraycopy(boxes[i], 0, this.map[i], 0, this.size);
		}
	}
	
	public int getSize() {
		return this.size;
	}
	public int getOriginX() {
		return this.originX;
	}
	public int getOriginY() {
		return this.originY;
	}
	/**
	 * 
	 * @param X assoluto
	 * @param Y assoluto
	 * @return un valore appartenente a BoxType
	 */
	public BoxType typeOf(int[] coordinates){
		try{
			return this.map[coordinates[0] - this.originX][coordinates[1] - this.originY];
		} catch (IndexOutOfBoundsException e){
			throw new IllegalArgumentException();
		}
	}
	
	/**
	 * 
	 * @param X assoluto
	 * @param Y assoluto
	 * @return il valore, se esistente, dell'energia O l'id del dinosauro
	 */
	public int valueOf(int[] coordinates){
		try{
			if (this.typeOf(coordinates) == BoxType.MEAT ||
				this.typeOf(coordinates) == BoxType.VEGE ||
				this.typeOf(coordinates) == BoxType.DINO ){
				return this.values[coordinates[0] - this.originX][coordinates[1] - this.originY];
			}
			
			throw new IllegalArgumentException();
		} catch (IndexOutOfBoundsException e){
			throw new IllegalArgumentException();
		}
	}
	
	public void setValues(int[][] values){
		for (int i = 0;i < this.size;i++){
			System.arraycopy(values[i], 0, this.values[i], 0, this.size);
		}
	}
	
	public void merge(UserMap map){
		for (int i = map.getOriginX();i < map.getOriginX() + map.size;i++){
			for (int j = map.getOriginY();j < map.originY + map.size;j++){
				if (i < this.size && j < this.size){
					int relativeX = i - map.getOriginX();
					int relativeY = j - map.getOriginY();
					
					if (map.map[relativeX][relativeY] == null)
						continue;
					
					if (this.map[i][j] == null)
						this.map[i][j] = map.map[relativeX][relativeY];
					
					if (! this.map[i][j].equals(map.map[relativeX][relativeY])){
						this.map[i][j] = map.map[relativeX][relativeY];
					}
					if (! (this.values[i][j] == map.values[relativeX][relativeY])){
						this.values[i][j] = map.values[relativeX][relativeY];
					}
				}
			}
		}
	}
}
